home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
pcmagazi
/
1988
/
02
/
putenv.asm
< prev
next >
Wrap
Assembly Source File
|
1987-12-14
|
7KB
|
186 lines
name putenv
page 55,132
title PUTENV modify environment variable
;
; PUTENV.ASM --- add or modify environment variable
;
; (C) 1987 Ziff Communications Co, by Ray Duncan
;
; Call with: DS:SI = new ASCIIZ environment variable
; ES = segment of program segment prefix
;
; Returns: AX = 0 if successful, -1 if failed
DGROUP group _DATA
_TEXT segment word public 'CODE'
assume cs:_TEXT
public putenv ; make visible to Linker
extrn getenv:near
; names for working storage
oldenv equ [bp-2] ; segment of old environment
envlen equ [bp-4] ; length of old environment
newenv equ [bp-6] ; segment of new environment
pspseg equ [bp-8] ; segment of program segment prefix
oldlen equ [bp-10] ; length of existing variable
newlen equ [bp-12] ; length of new env. variable
newname equ [bp-14] ; offset of new name portion
newvar equ [bp-16] ; offset of new param. portion
putenv proc near ; modify/add environment variable
push bp ; set up stack frame for
mov bp,sp ; working storage
sub sp,16
mov newname,si ; save offset of new variable
mov pspseg,es ; save PSP segment
mov es,es:[002ch] ; pick up segment of old
mov oldenv,es ; environment and save it
push cx ; save other registers
push si
push di
; find old environment length
mov cx,8000h ; assume max = 32 KBytes
xor di,di ; ES:DI = environment base
xor al,al
put1: repne scasb ; scan for double null (can't use
scasb ; SCASW since might be on odd addr)
jne put1
mov envlen,di ; save length of old environment
mov di,si ; find length of new env. variable
mov ax,ds ; ES:DI = addr of new variable
mov es,ax
mov cx,-1
xor al,al
repne scasb ; scan for terminating null byte
not cx ; now CX = length including null
mov newlen,cx ; save length of new variable
; attempt to allocate memory
; block for new environment...
mov bx,cx ; length of old environment
add bx,envlen ; + length of new variable
mov cl,4 ; divide by 16 and round
shr bx,cl ; up to find paragraphs to
inc bx ; allocate for new environment
mov ah,48h ; Fxn 48h=allocate memory block
int 21h ; transfer to MS-DOS
jnc put2 ; jump if allocation succeeded
mov ax,-1 ; otherwise, return error flag
jmp put6
put2: mov newenv,ax ; save new environment segment
mov di,offset envar ; copy name portion of new
; variable to local storage
put3: movsb ; copy characters up to '='
cmp byte ptr [si],'='
jne put3 ; loop until end of name found
xor al,al ; append null byte to name
stosb
inc si ; save address of param.
mov newvar,si ; portion of new variable
mov si,offset envar ; check if new environment
mov es,oldenv ; variable has a previous value
call getenv ; in old environment
mov oldlen,ax ; save length of value, if any
or ax,ax ; was it present in old block?
jnz put4 ; yes, PUTENV the hard way
push ds ; no just copy existing environment
; and add the new variable
mov ds,oldenv ; DS:SI = old env. block
mov es,newenv ; ES:DI = new env. block
mov cx,envlen ; CX = length of old environment
dec cx ; less the extra null byte
xor si,si
xor di,di
rep movsb ; copy the old stuff
pop ds ; DS:SI = address of new variable
mov si,newname ; ES:DI = end of new environment
mov cx,newlen ; CX = length of new variable
rep movsb ; append the new variable
xor al,al ; and the extra null byte
stosb ; marking end of environment
jmp put5 ; go update PSP env. pointer
put4: ; come here on the messy case,
; env. variable already exists
; ES:DI = offset+1 of '=' in
; old variable from 'getenv'
push ds ; copy old environment to new
mov ax,es ; up through the '=' of the
mov ds,ax ; variable we are changing
mov cx,di ; DS:SI = old environment
mov es,newenv ; ES:DI = new environment
xor si,si ; CX = offset+1 of '='
xor di,di ; in old variable
rep movsb
pop ds ; now let DS:SI = offset+1
push si ; of '=' in new variable
mov si,newvar ; and CX = length of portion
mov cx,newname ; following the '='
add cx,newlen
sub cx,newvar ; copy the new parameter portion
rep movsb ; to the new environment
pop si ; skip over parameter portion
add si,oldlen ; of the old variable
inc si ; and its null byte
push ds ; now copy remainder of
mov ds,oldenv ; old environment to new one
mov cx,envlen ; total length less portion
sub cx,si ; already copied and length
rep movsb ; of old environment variable
pop ds
put5: ; PUTENV function successful,
mov es,oldenv ; release old environment block
mov ah,49h
int 21h ; transfer to MS-DOS
mov es,pspseg ; update pointer to new
mov ax,newenv ; environment in caller's PSP
mov es:[002ch],ax
xor ax,ax ; return success code
put6: pop di ; restore registers
pop si
pop cx
mov sp,bp ; discard stack frame
pop bp
ret ; back to caller
putenv endp
_TEXT ends
_DATA segment word public 'DATA'
envar db 80 dup (0) ; name of new environment var.
; for call to 'getenv'
_DATA ends
end